//
//  MyCamera.m
//  IOTCamViewer
//
//  Created by Cloud Hsiao on 12/7/2.
//  Copyright (c) 2012年 TUTK. All rights reserved.
//

#import "MyCamera.h"
#import <IOTCamera/AVIOCTRLDEFs.h>
#import <IOTCamera/AVFrameInfo.h>

//#import "Alarm433Device.h"

#import "defines.h"

BOOL g_bDiagnostic = FALSE;

@interface MyCamera()

@property(readwrite) NSInteger remoteNotifications;

@end

@implementation MyCamera
@synthesize delegate2;
@synthesize delegate3;
@synthesize delegate4;

@synthesize lastChannel;
@synthesize remoteNotifications;
@synthesize viewAcc, viewPwd;
#if defined(P2PNETCAM_HAIER)
@synthesize viewPos;
#endif
@synthesize bIsSupportTimeZone;
@synthesize nGMTDiff;
@synthesize strTimeZone;

//#if defined(P2PMENBOSHI) || defined(P2PBANDIANGOU) || defined(P2PPETWANT) || defined(P2PXBROBOT)
#if 1
@synthesize orgArming;
@synthesize newArming;

@synthesize isPushMode;
@synthesize isNewPushMode;
@synthesize pushSoundName;
@synthesize deviceType;
@synthesize isAddServerSuccess;
@synthesize deviceID;
@synthesize newVersionFlag;
@synthesize isReadNewVersionFlag;
@synthesize isProcessRemoteServer;
#endif

#if defined(P2PPETWANT) || defined(P2PONTIPS)
@synthesize petid;
#endif

#if defined(P2PONTIPS)
@synthesize authority;
@synthesize panelphone;
@synthesize adminphone;
#endif

#if defined(AUDIO_TO_SUPPORT)
@synthesize isRecvAudioFormat;
#endif

#if defined(DEV_LIST_CONTRL) || defined(P2PVIDEODB)
@synthesize orgContrlValue1;
@synthesize newContrlValue1;
#endif

@synthesize orgModeValue1;
@synthesize newModeValue1;
@synthesize isShowListView;

@synthesize externalDeviceListArr;

@synthesize cameraLocalRecorder;

#pragma mark - Public Methods

- (NSArray *)getSupportedStreams
{
    return [arrayStreamChannel count] == 0 ? nil : [[NSArray alloc] initWithArray:arrayStreamChannel];
}

- (BOOL)getAudioInSupportOfChannel:(NSInteger)channel
{
    return ([self getServiceTypeOfChannel:channel] & 1) == 0;
}

- (BOOL)getAudioOutSupportOfChannel:(NSInteger)channel
{
    return ([self getServiceTypeOfChannel:channel] & 2) == 0;
}

- (BOOL)getPanTiltSupportOfChannel:(NSInteger)channel
{
    return ([self getServiceTypeOfChannel:channel] & 4) == 0;
}

- (BOOL)getEventListSupportOfChannel:(NSInteger)channel
{
    return ([self getServiceTypeOfChannel:channel] & 8) == 0;
}

- (BOOL)getPlaybackSupportOfChannel:(NSInteger)channel
{
    return ([self getServiceTypeOfChannel:channel] & 16) == 0;
}

- (BOOL)getWiFiSettingSupportOfChannel:(NSInteger)channel
{
    return ([self getServiceTypeOfChannel:channel] & 32) == 0;
}

- (BOOL)getMotionDetectionSettingSupportOfChannel:(NSInteger)channel
{
    return ([self getServiceTypeOfChannel:channel] & 64) == 0;
}

- (BOOL)getRecordSettingSupportOfChannel:(NSInteger)channel
{
    return ([self getServiceTypeOfChannel:channel] & 128) == 0;
}

- (BOOL)getFormatSDCardSupportOfChannel:(NSInteger)channel
{
    return ([self getServiceTypeOfChannel:channel] & 256) == 0;
}

- (BOOL)getVideoFlipSupportOfChannel:(NSInteger)channel
{
    return ([self getServiceTypeOfChannel:channel] & 512) == 0;
}

- (BOOL)getEnvironmentModeSupportOfChannel:(NSInteger)channel
{
    return ([self getServiceTypeOfChannel:channel] & 1024) == 0;
}

- (BOOL)getMultiStreamSupportOfChannel:(NSInteger)channel
{
    return ([self getServiceTypeOfChannel:channel] & 2048) == 0;
}

- (NSInteger)getAudioOutFormatOfChannel:(NSInteger)channel
{
    return ([self getServiceTypeOfChannel:channel] & 4096) == 0 ? MEDIA_CODEC_AUDIO_SPEEX : MEDIA_CODEC_AUDIO_ADPCM;
}

- (BOOL)getVideoQualitySettingSupportOfChannel:(NSInteger)channel
{
    return ([self getServiceTypeOfChannel:channel] & 8192) == 0;
}

- (BOOL)getDeviceInfoSupportOfChannel:(NSInteger)channel
{
    return ([self getServiceTypeOfChannel:channel] & 16384) == 0;
}

- (BOOL)getDeviceUpgradeOnlineSupportOfChannel:(NSInteger)channel
{
    //18
    return (([self getServiceTypeOfChannel:channel] & (1<<18)) > 0);
}

- (BOOL)getDevicePTZSupportOfChannel:(NSInteger)channel
{
    //19
    return (([self getServiceTypeOfChannel:channel] & (1<<19)) > 0);
}

- (BOOL)getDeviceRestorySupportOfChannel:(NSInteger)channel
{
    //20
    return (([self getServiceTypeOfChannel:channel] & (1<<20)) > 0);
}

- (BOOL)getDeviceRebootSupportOfChannel:(NSInteger)channel
{
    //21
    return (([self getServiceTypeOfChannel:channel] & (1<<21)) > 0);
}

- (BOOL)getDeviceIRCutSupportOfChannel:(NSInteger)channel
{
    //22
    return (([self getServiceTypeOfChannel:channel] & (1<<22)) > 0);
}

- (BOOL)getDeviceArmSupportOfChannel:(NSInteger)channel
{
    //23
    return (([self getServiceTypeOfChannel:channel] & (1<<23)) > 0);
}

- (BOOL)getDeviceWarnSupportOfChannel:(NSInteger)channel
{
    //24
    return (([self getServiceTypeOfChannel:channel] & (1<<24)) > 0);
}

- (BOOL)getPWDeviceLowProfileSupportOfChannel:(NSInteger)channel
{
    //27
    return (([self getServiceTypeOfChannel:channel] & (1<<27)) > 0);
}

#pragma mark -



- (void)myInit {
    //#if defined(P2PMENBOSHI) || defined(P2PBANDIANGOU) || defined(P2PPETWANT) || defined(P2PXBROBOT)
#if 1
    self.orgArming = -1;
    self.newArming = -1;
    
#if defined(P2PBANDIANGOU) || defined(P2PPETWANT) || defined(P2PWEXVS)  || defined(P2PAUROCAM_WEX) // test
    self.isPushMode = 1;
    self.isNewPushMode = 0;
#else
    self.isPushMode = -1;
    
    
#endif
    
    self.isWrongPassword = 0;
    self.isProcessRemoteServer = 0;
    self.currentEventType = 0;
    self.currentEventTime = 0;
    
    self.pushSoundName = [[NSString alloc] initWithString:@""];
    self.deviceType = [[NSString alloc] initWithString:@""];
    self.isAddServerSuccess = 0;
    self.deviceID = [[NSString alloc] initWithString:@""];
    
    self.newVersionFlag = -1;
    self.isReadNewVersionFlag = 0;
#endif
    
#if defined(P2PPETWANT) || defined(P2PONTIPS)
    self.petid = [[NSString alloc] initWithString:@""];
#endif
    
#if defined(P2PONTIPS)
    self.authority = [[NSString alloc] initWithString:@""];
    self.panelphone = [[NSString alloc] initWithString:@""];
    self.adminphone = [[NSString alloc] initWithString:@""];
#endif
    
#if defined(DEV_LIST_CONTRL) || defined(P2PVIDEODB)
    self.orgContrlValue1 = -1;
    self.newContrlValue1 = -1;
#endif
    
#if defined(AUDIO_TO_SUPPORT)
    isRecvAudioFormat = NO;
#endif
    
    self.orgModeValue1 = -1;
    self.newModeValue1 = -1;
    self.isShowListView = NO;
    
    self.externalDeviceListArr = [[NSMutableArray alloc] init];
    //test
#if defined(P2PBANDIANGOU)
    
    Alarm433Device *dev = [[Alarm433Device alloc] init];
    dev.alias = @"X";
    dev.orgIsAllow = YES;
    dev.newIsAllow = YES;
    [self.externalDeviceListArr addObject:dev];
    
    dev = [[Alarm433Device alloc] init];
    dev.alias = @"YY";
    dev.orgIsAllow = NO;
    dev.newIsAllow = NO;
    [self.externalDeviceListArr addObject:dev];
    
    dev = [[Alarm433Device alloc] init];
    dev.alias = @"ZZZ";
    dev.orgIsAllow = NO;
    dev.newIsAllow = NO;
    [self.externalDeviceListArr addObject:dev];
    
    dev = [[Alarm433Device alloc] init];
    dev.alias = @"VVVV";
    dev.orgIsAllow = NO;
    dev.newIsAllow = NO;
    [self.externalDeviceListArr addObject:dev];
    
    dev = [[Alarm433Device alloc] init];
    dev.alias = @"WWWWW";
    dev.orgIsAllow = NO;
    dev.newIsAllow = NO;
    [self.externalDeviceListArr addObject:dev];
    
#endif
}

- (id)init
{
    self = [super init];
    if (self) {
        arrayStreamChannel = [[NSMutableArray alloc] init];
        self.remoteNotifications = 0;
        
        [self myInit];
        
        self.delegate = self;
    }
    return self;
}


#if defined(P2PNETCAM_HAIER)
- (id)initWithName:(NSString *)name viewAccount:(NSString *)viewAcc_ viewPassword:(NSString *)viewPwd_ viewPosition:(NSString *)viewPos_
{
    self = [super initWithName:name];
    
    [self myInit];
    
    self.viewPos = viewPos_;
#else
    - (id)initWithName:(NSString *)name viewAccount:(NSString *)viewAcc_ viewPassword:(NSString *)viewPwd_
    {
        self = [super initWithName:name];
#endif
        
        if (self) {
            arrayStreamChannel = [[NSMutableArray alloc] init];
            self.viewAcc = viewAcc_;
            self.viewPwd = viewPwd_;
            self.remoteNotifications = 0;
            
            [self myInit];
            
            self.delegate = self;
        }
        
        return self;
    }
    
    - (void)dealloc
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self name:@"didReceiveIOCtrl" object:nil];
        [arrayStreamChannel release];
        [strTimeZone release];
        self.delegate2 = nil;
        self.delegate3 = nil;
        
        [self.pushSoundName release];
        self.pushSoundName = nil;
        
        [self.deviceType release];
        self.deviceType = nil;
        [self.deviceID release];
        self.deviceID = nil;
        
#if defined(P2PPETWANT) || defined(P2PONTIPS)
        [self.petid release];
        self.petid = nil;
#endif
        
#if defined(P2PONTIPS)
        [self.authority release];
        self.authority = nil;
        [self.panelphone release];
        self.panelphone = nil;
        [self.adminphone release];
        self.adminphone = nil;
#endif
        
        [self.externalDeviceListArr release];
        self.externalDeviceListArr = nil;
        
        [super dealloc];
    }
    
    - (void)start:(NSInteger)channel
    {
        strTimeZone = [[NSString alloc] init];
#ifdef LIB_140210
        [super start:channel viewAccount:viewAcc viewPassword:viewPwd is_playback:FALSE];
#else
        [super start:channel viewAccount:viewAcc viewPassword:viewPwd];
#endif
    }
    
#ifdef LIB_140210
    - (void)start4EventPlayback:(NSInteger)channel
    {
        //bIsSupportTimeZone = 1;
        //nGMTDiff = 8*60;
        strTimeZone = [[NSString alloc] init];
        
        [super start:channel viewAccount:viewAcc viewPassword:viewPwd is_playback:TRUE];
    }
#endif
    
    - (void)setRemoteNotification:(NSInteger)type EventTime:(long)time
    {
        remoteNotifications++;
        
        NSLog(@"remoteNotifications:%ld", (long)remoteNotifications);
        
        if (self.delegate2 != nil && [self.delegate2 respondsToSelector:@selector(camera:_didReceiveRemoteNotification:EventTime:)]) {
            [self.delegate2 camera:self _didReceiveRemoteNotification:type EventTime:time];
        }
    }
    
    - (void)clearRemoteNotifications
    {
        remoteNotifications = 0;
    }
    
#pragma mark - CameraDelegate Methods
    - (void)camera:(Camera *)camera didReceiveRawDataFrame:(const char *)imgData VideoWidth:(NSInteger)width VideoHeight:(NSInteger)height
    {
        if (self.delegate2 && [self.delegate2 respondsToSelector:@selector(camera:_didReceiveRawDataFrame:VideoWidth:VideoHeight:)]) {
            [self.delegate2 camera:self _didReceiveRawDataFrame:imgData VideoWidth:width VideoHeight:height];
        }
    }
    
    - (void)camera:(Camera *)camera didReceiveJPEGDataFrame:(const char *)imgData DataSize:(NSInteger)size
    {
        if (self.delegate2 && [self.delegate2 respondsToSelector:@selector(camera:_didReceiveJPEGDataFrame:DataSize:)]) {
            [self.delegate2 camera:self _didReceiveJPEGDataFrame:imgData DataSize:size];
        }
    }
    
    - (void)camera:(Camera *)camera didReceiveFrameInfoWithVideoWidth:(NSInteger)videoWidth VideoHeight:(NSInteger)videoHeight VideoFPS:(NSInteger)fps VideoBPS:(NSInteger)videoBps AudioBPS:(NSInteger)audioBps OnlineNm:(NSInteger)onlineNm FrameCount:(unsigned int)frameCount IncompleteFrameCount:(unsigned int)incompleteFrameCount
    {
        if (self.delegate2 && [self.delegate2 respondsToSelector:@selector(camera:_didReceiveFrameInfoWithVideoWidth:VideoHeight:VideoFPS:VideoBPS:AudioBPS:OnlineNm:FrameCount:IncompleteFrameCount:)]) {
            [self.delegate2 camera:self _didReceiveFrameInfoWithVideoWidth:videoWidth VideoHeight:videoHeight VideoFPS:fps VideoBPS:videoBps AudioBPS:audioBps OnlineNm:onlineNm FrameCount:frameCount IncompleteFrameCount:incompleteFrameCount];
        }
    }
    
    - (void)camera:(Camera *)camera didChangeSessionStatus:(NSInteger)status
    {
        if (self.delegate2 && [self.delegate2 respondsToSelector:@selector(camera:_didChangeSessionStatus:)]) {
            [self.delegate2 camera:self _didChangeSessionStatus:status];
        }
        
#if defined(SYNC_REMOTE_SERVER)
        if (self.delegate3 && [self.delegate3 respondsToSelector:@selector(camera:_didChangeSessionStatus:)]) {
            
            [self.delegate3 camera:self _didChangeSessionStatus:status];
        }
#endif
        
#if defined(P2PPETWANT)
        if (self.delegate4 && [self.delegate4 respondsToSelector:@selector(camera:_didChangeSessionStatus:)]) {
            [self.delegate4 camera:self _didChangeSessionStatus:status];
        }
#endif
        
        if (self.sessionState == CONNECTION_STATE_UNKNOWN_DEVICE ||
            self.sessionState == CONNECTION_STATE_UNSUPPORTED ||
            self.sessionState == CONNECTION_STATE_CONNECT_FAILED) {
            
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
                
                [self disconnect];
                
            });
        }
    }
    
    - (void)camera:(Camera *)camera didChangeChannelStatus:(NSInteger)channel ChannelStatus:(NSInteger)status
    {
        if (self.delegate2 && [self.delegate2 respondsToSelector:@selector(camera:_didChangeChannelStatus:ChannelStatus:)]) {
            [self.delegate2 camera:self _didChangeChannelStatus:channel ChannelStatus:status];
        }
        
#if defined(SYNC_REMOTE_SERVER)
        
        if (self.delegate3 && [self.delegate3 respondsToSelector:@selector(camera:_didChangeChannelStatus:ChannelStatus:)]) {
            
            [self.delegate3 camera:self _didChangeChannelStatus:channel ChannelStatus:status];
        }
#endif
        
#if defined(P2PPETWANT)
        if (self.delegate4 && [self.delegate4 respondsToSelector:@selector(camera:_didChangeChannelStatus:ChannelStatus:)]) {
            [self.delegate4 camera:self _didChangeChannelStatus:channel ChannelStatus:status];
        }
#endif
        
        if (status == CONNECTION_STATE_WRONG_PASSWORD) {
            
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
                
                [self stop:channel];
                
                usleep(500 * 1000);
                
                [self disconnect];
            });
        }
    }
    
    - (void)camera:(Camera *)camera didReceiveIOCtrlWithType:(NSInteger)type Data:(const char*)data DataSize:(NSInteger)size
    {
        if (self.delegate2 && [self.delegate2 respondsToSelector:@selector(camera:_didReceiveIOCtrlWithType:Data:DataSize:)]) {
            [self.delegate2 camera:self _didReceiveIOCtrlWithType:type Data:data DataSize:size];
        }
        
#if defined(P2PPUSH)
        // for push
        if (self.delegate3 && [self.delegate3 respondsToSelector:@selector(camera:_didReceiveIOCtrlWithType:Data:DataSize:)]) {
            [self.delegate3 camera:self _didReceiveIOCtrlWithType:type Data:data DataSize:size];
        }
#endif
        
#if defined(P2PPETWANT)
        // for
        
        if (self.delegate4 && [self.delegate4 respondsToSelector:@selector(camera:_didReceiveIOCtrlWithType:Data:DataSize:)]) {
            [self.delegate4 camera:self _didReceiveIOCtrlWithType:type Data:data DataSize:size];
        }
#endif
        
        NSData *buf = [NSData dataWithBytes:data length:size];
        NSNumber *t = [NSNumber numberWithInt:(int)type];
        NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: buf, @"recvData", t, @"type", self.uid, @"uid", nil];
        [[NSNotificationCenter defaultCenter] postNotificationName:@"didReceiveIOCtrl" object:self userInfo:dict];
        
        if (type == (int)IOTYPE_USER_IPCAM_GETSUPPORTSTREAM_RESP) {
            
            [arrayStreamChannel removeAllObjects];
            
            SMsgAVIoctrlGetSupportStreamResp *s = (SMsgAVIoctrlGetSupportStreamResp *)data;
            
            if (s->number > 0) {
                SStreamDef *def = malloc(size - (sizeof(s->number)));
                memcpy(def, s->streams, size - (sizeof(s->number)));
                
                for (int i = 0; i < s->number; i++) {
                    
                    SubStream_t ch;
                    ch.index = def[i].index;
                    ch.channel = def[i].channel;
                    
                    NSValue *objCh = [[NSValue alloc] initWithBytes:&ch objCType:@encode(SubStream_t)];
                    [arrayStreamChannel addObject:objCh];
                    [objCh release];
                    
                    if (def[i].channel != 0) {
                        // NSString *acc = [self getViewAccountOfChannel:0];
                        // NSString *pwd = [self getViewPasswordOfChannel:0];
#if defined(LIB_140210)
                        [self start:def[i].channel viewAccount:self.viewAcc viewPassword:self.viewPwd is_playback:FALSE];
#else
                        [self start:def[i].channel viewAccount:self.viewAcc viewPassword:self.viewPwd];
#endif
                    }
                }
                free(def);
            }
        }
        
#if defined(AUDIO_TO_SUPPORT)
        else if (type == IOTYPE_USER_IPCAM_GETAUDIOOUTFORMAT_RESP) {
            SMsgAVIoctrlGetAudioOutFormatResp *s = (SMsgAVIoctrlGetAudioOutFormatResp *)data;
            
            NSLog(@"MyCamera IOTYPE_USER_IPCAM_GETAUDIOOUTFORMAT_RESP s->format:%d", s->format);
            
            isRecvAudioFormat = YES;
        }
#endif
        else if(type == (int)IOTYPE_USER_IPCAM_GET_TIMEZONE_RESP) {
            SMsgAVIoctrlTimeZone* p = (SMsgAVIoctrlTimeZone*)data;
            
            if( p->cbSize == sizeof(SMsgAVIoctrlTimeZone) ) {
                NSLog( @">>>> IOTYPE_USER_IPCAM_GET_TIMEZONE_RESP <OK>\n\tbIsSupportTimeZone:%d\n\tnGMTDiff:%d\n\tstrTimeZone:%@", p->nIsSupportTimeZone, p->nGMTDiff, ( strlen(p->szTimeZoneString) > 0 ) ? [NSString stringWithUTF8String:p->szTimeZoneString]:@"(null)" );
                bIsSupportTimeZone = p->nIsSupportTimeZone;
                nGMTDiff = p->nGMTDiff;
                NSString* pTimeZoneStringFromDevice = nil;
                if( strlen(p->szTimeZoneString) > 0 )
                    pTimeZoneStringFromDevice = [NSString stringWithUTF8String:p->szTimeZoneString];
                
                self.strTimeZone =pTimeZoneStringFromDevice ;
            }
        }
    }
    
    @end
